home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 20
/
Cream of the Crop 20 (Terry Blount) (1996).iso
/
os2
/
souper15.zip
/
NEWS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-18
|
26KB
|
1,135 lines
/* $Id: news.c 1.6 1996/05/18 21:06:26 cthuang Exp $
*
* Get news from NNTP server.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "socket.h"
#include "nntp.h"
#include "nntpcl.h"
#include "souper.h"
/* article number range in the .newsrc file */
typedef struct aRange {
struct aRange *next; /* pointer to next */
ArticleNumber lo, hi; /* article number range */
} Range;
/* newsgroup entry in the .newsrc file */
typedef struct aNewsrcGroup {
struct aNewsrcGroup *next; /* pointer to next */
char *name; /* newsgroup name */
Range *readList; /* list of read article ranges */
char subscribed; /* subscribed flag */
} NewsrcGroup;
static NewsrcGroup *nrcList; /* list of .newsrc entries. */
static long byteCount; /* current size of fetched news */
static char killEnabled; /* kill processing enabled for this group */
static FILE *tmpF; /* temporary file for article */
static int groupCnt; /* current group number */
#ifdef __WIN32__
#include <conio.h>
#endif
/* Read the article numbers from a .newsrc line. */
static Range *
getReadList (FILE *nrcFile)
{
static const char digits[] = "%[0123456789]";
Range *pLast, *rp, *head;
ArticleNumber lo, hi;
int c;
char *range;
char buf[20];
/* Initialize subscription list */
pLast = NULL;
head = NULL;
/* Expect [ \n] */
c = fgetc(nrcFile);
while (c != '\n' && c != EOF) {
/* Expect number */
if (fscanf(nrcFile, digits, buf) != 1)
break;
lo = atol(buf);
/* Get space for new list entry */
rp = (Range *)xmalloc(sizeof(Range));
/* Expect [-,\n] */
c = fgetc(nrcFile);
if (c == '-') {
/* Is a range */
/* Expect number */
if (fscanf(nrcFile, digits, buf) != 1)
break;
hi = atol(buf);
rp->lo = lo;
rp->hi = hi;
if (lo != 1 || hi != 0) {
/* Reverse them in case they're backwards */
if (hi < lo) {
rp->lo = hi;
rp->hi = lo;
}
}
/* Expect [,\n] */
c = fgetc(nrcFile);
} else {
/* Not a range */
rp->lo = rp->hi = lo;
}
/* Check if range overlaps last one */
if (pLast != NULL && rp->lo <= pLast->hi + 1) {
/* Combine ranges */
if (rp->lo < pLast->lo) pLast->lo = rp->lo;
if (rp->hi > pLast->hi) pLast->hi = rp->hi;
/* Free old one */
free(rp);
} else {
/* No overlap, update pointers */
if (pLast == NULL) {
head = rp;
} else {
pLast->next = rp;
}
rp->next = NULL;
pLast = rp;
}
}
while (c != '\n' && c != EOF)
c = fgetc(nrcFile);
return head;
}
/* Read the .newsrc file and point nrcList to list of newsgroups entries.
* Return TRUE if successful.
*/
static int
readNewsrc (void)
{
FILE *nrcFile;
char group_name[BUFSIZ], ch;
NewsrcGroup *head, *np, *lnp;
/* lnp points to last entry */
lnp = NULL;
head = NULL;
/* Open it */
if ((nrcFile = fopen(newsrcFile, "r")) == NULL) {
fprintf(stderr, "%s: can't open %s\n", progname, newsrcFile);
return 0;
}
/* Read newsgroup entry */
while (fscanf(nrcFile, "%[^:! \t\n]", group_name) == 1) {
if (group_name[0] == '\0')
break;
/* Allocate a new entry */
np = (NewsrcGroup *)xmalloc(sizeof(NewsrcGroup));
ch = fgetc(nrcFile);
if (ch == '\n') {
/* The user didn't end the line with a colon. */
np->subscribed = 1;
np->readList = NULL;
} else {
/* Parse subscription list */
np->subscribed = (ch == ':');
np->readList = getReadList(nrcFile);
}
np->name = xstrdup(group_name);
np->next = NULL;
/* Add to list */
if (lnp == NULL) {
head = np;
} else {
lnp->next = np;
}
lnp = np;
}
fclose(nrcFile);
nrcList = head;
return 1;
}
/* Write the article numbers for a .newsrc entry. */
static void
putReadList (FILE *fd, Range *head)
{
while (head != NULL) {
if (head->lo == head->hi)
fprintf(fd, "%ld", head->lo);
else
fprintf(fd, "%ld-%ld", head->lo, head->hi);
head = head->next;
if (head != NULL) fputc(',', fd);
}
fputc('\n', fd);
}
/* Rewrite the updated .newsrc file. */
int
writeNewsrc (void)
{
char oldFile[FILENAME_MAX];
FILE *nrcFile;
NewsrcGroup *np;
if (readOnly || !doNews || !nrcList) return 0;
/* Back up old .newsrc file. */
sprintf(oldFile, "%s.old", newsrcFile);
remove(oldFile);
rename(newsrcFile, oldFile);
if ((nrcFile = fopen(newsrcFile, "w")) == NULL) {
fprintf(stderr, "%s: can't write %s\n", progname, newsrcFile);
return 0;
}
for (np = nrcList; np != NULL; np = np->next) {
fputs(np->name, nrcFile);
fputc(np->subscribed ? ':' : '!', nrcFile);
fputc(' ', nrcFile);
putReadList(nrcFile, np->readList);
}
fclose(nrcFile);
return 1;
}
/* Get first unread article number. */
static ArticleNumber
firstUnread (Range *head, ArticleNumber lo)
{
if (head == NULL)
return lo;
return head->hi + 1;
}
/* Determine if the article number has been read */
static int
isRead (ArticleNumber num, Range *head)
{
/* Look through the list */
while (head != NULL) {
if (num < head->lo) return 0;
if (num >= head->lo && num <= head->hi) return 1;
head = head->next;
}
return 0;
}
/* Mark article as read. */
static Range *
markRead (ArticleNumber num, Range *head)
{
Range *rp, *trp, *lrp;
rp = head;
/* If num is much lower than lowest range, or the list is
empty, we need new entry */
if (rp == NULL || num < rp->lo - 1) {
trp = (Range *)xmalloc(sizeof(Range));
trp->lo = trp->hi = num;
trp->next = rp;
return trp;
}
/* lrp remembers last entry in case we need to add a new entry */
lrp = NULL;
/* Find appropriate entry for this number */
while (rp != NULL) {
/* Have to squeeze one in before this one? */
if (num < rp->lo - 1) {
trp = (Range *)xmalloc(sizeof(Range));
trp->lo = trp->hi = num;
trp->next = rp;
lrp->next = trp;
return head;
}
/* One less than entry's lo? */
if (num == rp->lo - 1) {
rp->lo = num;
return head;
}
/* In middle of range, do nothing */
if (num >= rp->lo && num <= rp->hi) return head;
/* One too high, must check if we merge with next entry */
if (num == rp->hi + 1) {
if (rp->next != NULL && num == rp->next->lo - 1) {
trp = rp->next;
rp->hi = trp->hi;
rp->next = trp->next;
free(trp);
return head;
} else {
/* No merge */
rp->hi = num;
return head;
}
}
lrp = rp;
rp = rp->next;
}
/* We flew off the end and need a new entry */
trp = (Range *)xmalloc(sizeof(Range));
trp->lo = trp->hi = num;
trp->next = NULL;
lrp->next = trp;
return head;
}
/* Sanity fixes to the read article number list */
static Range *
fixReadList (NewsrcGroup *np, ArticleNumber lo, ArticleNumber hi)
{
Range *head, *rp1, *rp2, *rp3;
head = np->readList;
if (head != NULL) {
/* Go to last entry in list. */
for (rp1 = head; rp1->next != NULL; rp1 = rp1->next)
;
if (rp1->hi > hi) {
/* The highest read article number is greater than the highest
* available article number.
*/
#if 0
printf("%s: Somebody reset %s -- assuming nothing read.\n",
progname, np->name);
#endif
/* Mark everything as read. */
head->lo = 1;
head->hi = hi;
/* Free the rest */
rp2 = head->next;
while (rp2 != NULL) {
rp3 = rp2->next;
free(rp2);
rp2 = rp3;
}
#if 0
/* If lowest available article is 1, then leave read list empty,
* otherwise when group is reset, the first article would be
* skipped.
*/
if (lo <= 1) {
free(head);
return NULL;
}
#endif
head->next = NULL;
return head;
}
/* Walk through the list and eliminate ranges lower than the lowest
* available article
*/
rp1 = he